package cn.virens.common.mybatis.mapper.example.base;

import cn.virens.common.mybatis.mapper.example.ExampleCriteria;
import cn.virens.common.mybatis.mapper.example.ExampleHaving;
import cn.virens.common.mybatis.mapper.example.ExampleJoin;
import cn.virens.common.util.core.Assert;
import cn.virens.common.util.exception.APIException;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@SuppressWarnings("serial")
public abstract class AbstractExample implements Serializable {
    protected final List<ExampleCriteria> criteriaList = new ArrayList<>();
    protected final List<ExampleHaving> havingList = new ArrayList<>();
    protected final List<ExampleJoin> joinList = new ArrayList<>();

    protected final Set<String> excludeColumns = new HashSet<>();
    protected final Set<String> selectColumns = new HashSet<>();

    protected String orderByClause; // 排序字段
    protected String groupByClause; // 分组字段
    protected String limitByClause; // 分页字段

    /**
     * 获取排序规则
     *
     * @return 排序规则
     */
    public String getOrderByClause() {
        return orderByClause;
    }

    /**
     * 设置排序规则
     *
     * @param orderByClause 排序规则
     */
    public void setOrderByClause(String orderByClause) {
        this.orderByClause = orderByClause;
    }

    /**
     * 获取分组规则
     *
     * @return 分组规则
     */
    public String getGroupByClause() {
        return groupByClause;
    }

    /**
     * 设置分组规则
     *
     * @param groupByClause 分组规则
     */
    public void setGroupByClause(String groupByClause) {
        this.groupByClause = groupByClause;
    }

    /**
     * 获取限定规则
     *
     * @return 限定规则
     */
    public String getLimitByClause() {
        return limitByClause;
    }

    /**
     * 设置限定规则
     *
     * @param limitByClause 限定规则
     */
    public void setLimitByClause(String limitByClause) {
        this.limitByClause = limitByClause;
    }

    /**
     * 设置限定规则
     *
     * @param limit 数据条数
     */
    public void setLimitByClause(Integer limit) {
        this.setLimitByClause(String.valueOf(limit));
    }

    /**
     * 设置限定规则
     *
     * @param limit  数据条数
     * @param offset 起始偏移
     */
    public void setLimitByClause(Integer limit, Integer offset) {
        this.setLimitByClause(offset + "," + limit);
    }

    /**
     * 获取连表规则
     *
     * @return 连表规则
     * @throws APIException 一般异常
     */
    public List<ExampleJoin> getJoinList() throws APIException {
        return joinList.stream().filter(a -> {
            return a != null && a.isVerify();
        }).collect(Collectors.toList());
    }

    /**
     * 获取GROUP_BY条件
     *
     * @return GROUP_BY条件
     * @throws APIException 一般异常
     */
    public List<ExampleHaving> getHavingList() throws APIException {
        return havingList.stream().filter(a -> {
            return a != null && a.isVerify();
        }).collect(Collectors.toList());
    }

    /**
     * 获取条件规则
     *
     * @return 条件规则
     * @throws APIException 一般异常
     */
    public List<ExampleCriteria> getCriteriaList() throws APIException {
        return criteriaList.stream().filter(a -> {
            return a != null && a.isVerify();
        }).collect(Collectors.toList());
    }

    /**
     * 获取指定的查询字段列表
     *
     * @return 指定的查询字段列表
     */
    public Set<String> getSelectColumns() {
        return selectColumns;
    }

    /**
     * 获取排除的查询字段列表
     *
     * @return 排除的查询字段列表
     */
    protected Set<String> getExcludeColumns() {
        return excludeColumns;
    }

    /**
     * 添加指定的查询字段列表
     *
     * @param columns 指定的查询字段列表
     * @throws APIException Null异常
     */
    public void addSelectColumns(String... columns) throws APIException {
        for (String column : Assert.isNull(columns)) {
            this.selectColumns.add(column);
        }
    }

    /**
     * 添加排除的查询字段列表
     *
     * @param columns 排除的查询字段列表
     * @throws APIException Null异常
     */
    public void addExcludeColumns(String... columns) throws APIException {
        for (String column : Assert.isNull(columns)) {
            this.excludeColumns.add(column);
        }
    }

    /**
     * 添加条件规则
     *
     * @param criteria 条件规则
     * @return 条件规则
     */
    public ExampleCriteria addCriteria(ExampleCriteria criteria) {
        if (criteriaList.add(criteria)) {
            return criteria;
        } else {
            return null;
        }
    }

    /**
     * 添加GROUP_BY条件
     *
     * @param having GROUP_BY条件
     * @return GROUP_BY条件
     */
    public ExampleHaving addHaving(ExampleHaving having) {
        if (havingList.add(having)) {
            return having;
        } else {
            return null;
        }
    }

    /**
     * 添加连表规则
     *
     * @param join 连表规则
     * @return 连表规则
     */
    public ExampleJoin addJoin(ExampleJoin join) {
        if (joinList.add(join)) {
            return join;
        } else {
            return null;
        }
    }

}
